package me.tomassetti.turin.parser; import com.google.common.collect.ImmutableList; import me.tomassetti.parser.antlr.TurinParser; import me.tomassetti.turin.parser.ast.context.ContextDefinitionNode; import me.tomassetti.turin.parser.ast.typeusage.BasicTypeUsageNode; import me.tomassetti.turin.parser.ast.*; import me.tomassetti.turin.parser.ast.annotations.AnnotationUsage; import me.tomassetti.turin.parser.ast.expressions.*; import me.tomassetti.turin.parser.ast.expressions.literals.*; import me.tomassetti.turin.parser.ast.imports.*; import me.tomassetti.turin.parser.ast.invokables.FunctionDefinitionNode; import me.tomassetti.turin.parser.ast.invokables.TurinTypeContructorDefinitionNode; import me.tomassetti.turin.parser.ast.invokables.TurinTypeMethodDefinitionNode; import me.tomassetti.turin.parser.ast.properties.PropertyConstraint; import me.tomassetti.turin.parser.ast.properties.PropertyDefinition; import me.tomassetti.turin.parser.ast.properties.PropertyReference; import me.tomassetti.turin.parser.ast.relations.RelationDefinition; import me.tomassetti.turin.parser.ast.relations.RelationFieldDefinition; import me.tomassetti.turin.parser.ast.statements.*; import me.tomassetti.turin.parser.ast.typeusage.*; import me.tomassetti.turin.typesystem.PrimitiveTypeUsage; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.Token; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; class ParseTreeToAst { private Position getPosition(ParserRuleContext ctx) { return new Position(getStartPoint(ctx.start), getEndPoint(ctx.stop)); } private void getPositionFrom(Node node, ParserRuleContext ctx) { node.setPosition(getPosition(ctx)); } private Point getStartPoint(Token token) { return new Point(token.getLine(), token.getCharPositionInLine()); } private Point getEndPoint(Token token) { return new Point(token.getLine(), token.getCharPositionInLine() + token.getText().length()); } public TurinFile toAst(TurinParser.TurinFileContext ctx){ TurinFile turinFile = new TurinFile(); getPositionFrom(turinFile, ctx); turinFile.setNameSpace(toAst(ctx.namespace)); for (TurinParser.FileMemberContext memberCtx : ctx.fileMember()) { Node memberNode = toAst(memberCtx); if (memberNode instanceof TurinTypeDefinition) { turinFile.add((TurinTypeDefinition)memberNode); } else if (memberNode instanceof PropertyDefinition) { turinFile.add((PropertyDefinition) memberNode); } else if (memberNode instanceof Program) { turinFile.add((Program) memberNode); } else if (memberNode instanceof FunctionDefinitionNode) { turinFile.add((FunctionDefinitionNode)memberNode); } else if (memberNode instanceof RelationDefinition) { turinFile.add((RelationDefinition) memberNode); } else if (memberNode instanceof ContextDefinitionNode) { turinFile.add((ContextDefinitionNode) memberNode); } else { throw new UnsupportedOperationException(memberNode.getClass().getCanonicalName()); } } for (TurinParser.ImportDeclarationContext importDeclarationContext : ctx.importDeclaration()) { turinFile.add(toAst(importDeclarationContext)); } return turinFile; } private ImportDeclaration toAst(TurinParser.ImportDeclarationContext ctx) { if (ctx.allFieldsImportDeclaration() != null) { return toAst(ctx.allFieldsImportDeclaration()); } else if (ctx.singleFieldImportDeclaration() != null) { return toAst(ctx.singleFieldImportDeclaration()); } else if (ctx.typeImportDeclaration() != null) { return toAst(ctx.typeImportDeclaration()); } else if (ctx.allPackageImportDeclaration() != null) { AllPackageImportDeclaration node = new AllPackageImportDeclaration(toAst(ctx.allPackageImportDeclaration().packagePart)); getPositionFrom(node, ctx); return node; } else { throw new UnsupportedOperationException(ctx.toString()); } } private AllFieldsImportDeclaration toAst(TurinParser.AllFieldsImportDeclarationContext ctx) { AllFieldsImportDeclaration node = new AllFieldsImportDeclaration(toAst(ctx.packagePart), idText(ctx.typeName)); getPositionFrom(node, ctx); return node; } private ImportDeclaration toAst(TurinParser.TypeImportDeclarationContext ctx) { ImportDeclaration importDeclaration; if (ctx.alternativeName == null) { importDeclaration = new TypeImportDeclaration(toAst(ctx.packagePart), idText(ctx.typeName)); } else { importDeclaration = new TypeImportDeclaration(toAst(ctx.packagePart), idText(ctx.typeName), idText(ctx.alternativeName)); } getPositionFrom(importDeclaration, ctx); return importDeclaration; } private ImportDeclaration toAst(TurinParser.SingleFieldImportDeclarationContext ctx) { ImportDeclaration importDeclaration; if (ctx.alternativeName == null) { importDeclaration = new SingleFieldImportDeclaration(toAst(ctx.packagePart), idText(ctx.typeName), toAst(ctx.fieldName)); } else { importDeclaration = new SingleFieldImportDeclaration(toAst(ctx.packagePart), idText(ctx.typeName), toAst(ctx.fieldName), idText(ctx.alternativeName)); } getPositionFrom(importDeclaration, ctx); return importDeclaration; } private QualifiedName toAst(TurinParser.QualifiedIdContext ctx) { QualifiedName qualifiedName = QualifiedName.create(ctx.parts.stream().map((p) -> p.getText()).collect(Collectors.toList())); getPositionFrom(qualifiedName, ctx); return qualifiedName; } private Node toAst(TurinParser.FileMemberContext ctx) { if (ctx.typeDeclaration() != null) { return toAst(ctx.typeDeclaration()); } else if (ctx.topLevelPropertyDeclaration() != null) { return toAst(ctx.topLevelPropertyDeclaration()); } else if (ctx.program() != null) { return toAst(ctx.program()); } else if (ctx.topLevelFunctionDeclaration() != null) { return toAst(ctx.topLevelFunctionDeclaration()); } else if (ctx.relation() != null) { return toAst(ctx.relation()); } else if (ctx.contextDeclaration() != null) { return toAst(ctx.contextDeclaration()); } else { throw new UnsupportedOperationException(ctx.getClass().getCanonicalName()); } } private ContextDefinitionNode toAst(TurinParser.ContextDeclarationContext ctx) { ContextDefinitionNode contextDefinition = new ContextDefinitionNode(ctx.name.getText(), toAst(ctx.type)); getPositionFrom(contextDefinition, ctx); return contextDefinition; } private RelationDefinition toAst(TurinParser.RelationContext ctx) { List<RelationFieldDefinition> fields = ctx.relationField().stream().map((fCtx)->toAst(fCtx)).collect(Collectors.toList()); RelationDefinition relationDefinition = new RelationDefinition(ctx.name.getText(), fields); getPositionFrom(relationDefinition, ctx); return relationDefinition; } private RelationFieldDefinition toAst(TurinParser.RelationFieldContext ctx) { RelationFieldDefinition.Cardinality cardinality = null; if (ctx.one != null) { cardinality = RelationFieldDefinition.Cardinality.SINGLE; } else if (ctx.many != null) { cardinality = RelationFieldDefinition.Cardinality.MANY; } else { throw new UnsupportedOperationException(); } RelationFieldDefinition relationFieldDefinition = new RelationFieldDefinition(cardinality, ctx.name.getText(), toAst(ctx.type)); getPositionFrom(relationFieldDefinition, ctx); return relationFieldDefinition; } private FunctionDefinitionNode toAst(TurinParser.TopLevelFunctionDeclarationContext ctx) { List<FormalParameterNode> params = ctx.params.stream().map((p) -> toAst(p)).collect(Collectors.toList()); FunctionDefinitionNode functionDefinition = new FunctionDefinitionNode(idText(ctx.name), toAst(ctx.type), params, toAst(ctx.methodBody())); getPositionFrom(functionDefinition, ctx); ctx.annotations.forEach((anCtx)->{ AnnotationUsage annotationUsage = toAst(anCtx); functionDefinition.addAnnotation(annotationUsage); }); return functionDefinition; } private AnnotationUsage toAst(TurinParser.AnnotationUsageContext ctx) { // we skip the @ character AnnotationUsage annotationUsage = new AnnotationUsage(ctx.annotation.getText().substring(1)); getPositionFrom(annotationUsage, ctx); return annotationUsage; } private PropertyDefinition toAst(TurinParser.TopLevelPropertyDeclarationContext ctx) { Optional<Expression> initialValue = ctx.initialValue == null ? Optional.empty() : Optional.of(toAst(ctx.initialValue)); Optional<Expression> defaultValue = ctx.defaultValue == null ? Optional.empty() : Optional.of(toAst(ctx.defaultValue)); List<PropertyConstraint> constraints = Collections.emptyList(); PropertyDefinition propertyDefinition = new PropertyDefinition(idText(ctx.name), toAst(ctx.type), initialValue, defaultValue, constraints); getPositionFrom(propertyDefinition, ctx); return propertyDefinition; } private TurinTypeDefinition toAst(TurinParser.TypeDeclarationContext ctx) { TurinTypeDefinition typeDefinition = new TurinTypeDefinition(idText(ctx.name)); getPositionFrom(typeDefinition, ctx); for (TurinParser.TypeMemberContext memberCtx : ctx.typeMember()) { Node memberNode = toAst(memberCtx); if (memberNode instanceof PropertyReference) { typeDefinition.add((PropertyReference)memberNode); } else if (memberNode instanceof PropertyDefinition) { typeDefinition.add((PropertyDefinition) memberNode); } else if (memberNode instanceof TurinTypeMethodDefinitionNode) { typeDefinition.add((TurinTypeMethodDefinitionNode) memberNode); } else if (memberNode instanceof TurinTypeContructorDefinitionNode) { typeDefinition.add((TurinTypeContructorDefinitionNode) memberNode); } else { throw new UnsupportedOperationException(); } } ctx.annotations.forEach((anCtx)->{ AnnotationUsage annotationUsage = toAst(anCtx); typeDefinition.addAnnotation(annotationUsage); }); if (ctx.baseType != null) { typeDefinition.setBaseType(toAst(ctx.baseType)); } ctx.interfaze.forEach((iCtx)->typeDefinition.addInterface(toAst(iCtx))); return typeDefinition; } private Node toAst(TurinParser.TypeMemberContext ctx) { if (ctx.inTypePropertyDeclaration() != null) { return toAst(ctx.inTypePropertyDeclaration()); } else if (ctx.propertyReference() != null) { return toAst(ctx.propertyReference()); } else if (ctx.methodDefinition() != null) { return toAst(ctx.methodDefinition()); } else if (ctx.constructorDefinition() != null) { return toAst(ctx.constructorDefinition()); } else { throw new UnsupportedOperationException(ctx.getClass().getCanonicalName()); } } private Node toAst(TurinParser.MethodDefinitionContext ctx) { List<FormalParameterNode> params = ctx.params.stream().map((p) -> toAst(p)).collect(Collectors.toList()); TurinTypeMethodDefinitionNode methodDefinition = new TurinTypeMethodDefinitionNode(idText(ctx.name), toAst(ctx.type), params, toAst(ctx.methodBody())); getPositionFrom(methodDefinition, ctx); return methodDefinition; } private Node toAst(TurinParser.ConstructorDefinitionContext ctx) { List<FormalParameterNode> params = ctx.params.stream().map((p) -> toAst(p)).collect(Collectors.toList()); List<ActualParam> superParams = ctx.superParams.stream().map((p) -> toAst(p)).collect(Collectors.toList()); List<Statement> bodyStatements = ctx.statements.stream().map((s) -> toAst(s)).collect(Collectors.toList()); bodyStatements.add(new ExpressionStatement(new SuperInvokation(superParams))); BlockStatement body = new BlockStatement(bodyStatements); TurinTypeContructorDefinitionNode constructorDefinition = new TurinTypeContructorDefinitionNode(params, body); getPositionFrom(constructorDefinition, ctx); return constructorDefinition; } private Statement toAst(TurinParser.MethodBodyContext ctx) { if (ctx.expression() != null) { ReturnStatement returnStatement = new ReturnStatement(toAst(ctx.expression())); return new BlockStatement(ImmutableList.of(returnStatement)); } else if (ctx.statements != null) { return new BlockStatement(ctx.statements.stream().map((s)->toAst(s)).collect(Collectors.toList())); } else { throw new UnsupportedOperationException(); } } private FormalParameterNode toAst(TurinParser.FormalParamContext ctx) { FormalParameterNode formalParameter = new FormalParameterNode(toAst(ctx.type), idText(ctx.name)); getPositionFrom(formalParameter, ctx); return formalParameter; } private TypeUsageNode toAst(TurinParser.ReturnTypeContext type) { if (type.isVoid != null) { return new VoidTypeUsageNode(); } else if (type.type != null) { return toAst(type.type); } else { throw new UnsupportedOperationException(); } } private Node toAst(TurinParser.InTypePropertyDeclarationContext ctx) { Optional<Expression> initialValue = ctx.initialValue == null ? Optional.empty() : Optional.of(toAst(ctx.initialValue)); Optional<Expression> defaultValue = ctx.defaultValue == null ? Optional.empty() : Optional.of(toAst(ctx.defaultValue)); List<PropertyConstraint> constraints = ctx.constraint.stream().map((cctx)->toAst(cctx)).collect(Collectors.toList()); PropertyDefinition propertyDefinition = new PropertyDefinition( idText(ctx.name), toAst(ctx.type), initialValue, defaultValue, constraints); getPositionFrom(propertyDefinition, ctx); return propertyDefinition; } private PropertyConstraint toAst(TurinParser.ConstraintDeclarationContext ctx) { Expression condition = toAst(ctx.condition); Expression message = ctx.message == null ? new StringLiteral("Condition violated: " + ctx.condition.getText()) : toAst(ctx.message); PropertyConstraint propertyConstraint = new PropertyConstraint(condition, message); getPositionFrom(propertyConstraint, ctx); return propertyConstraint; } private PropertyReference toAst(TurinParser.PropertyReferenceContext propertyReferenceContext) { return new PropertyReference(idText(propertyReferenceContext.name)); } private TypeUsageNode toAst(TurinParser.TypeUsageContext type) { if (type.ref != null) { ReferenceTypeUsageNode referenceTypeUsage = new ReferenceTypeUsageNode(type.ref.getText()); getPositionFrom(referenceTypeUsage, type); return referenceTypeUsage; } else if (type.primitiveType != null) { return TypeUsageNode.wrap(PrimitiveTypeUsage.getByName(type.primitiveType.getText())); } else if (type.basicType != null) { return new BasicTypeUsageNode(type.basicType.getText()); } else if (type.arrayBase != null) { return new ArrayTypeUsageNode(toAst(type.arrayBase)); } else { throw new UnsupportedOperationException(type.getText()); } } private Node toAst(TurinParser.ProgramContext programCtx) { List<Statement> statements = new ArrayList<>(); for (TurinParser.StatementContext stmtCtx : programCtx.statements) { statements.add(toAst(stmtCtx)); } Program program = new Program(idText(programCtx.name), new BlockStatement(statements), idText(programCtx.formalParam.name)); getPositionFrom(program, programCtx); return program; } private Statement toAst(TurinParser.StatementContext stmtCtx) { if (stmtCtx.expressionStmt() != null) { return toAst(stmtCtx.expressionStmt()); } else if (stmtCtx.varDecl() != null) { return toAst(stmtCtx.varDecl()); } else if (stmtCtx.ifStmt() != null) { return toAst(stmtCtx.ifStmt()); } else if (stmtCtx.returnStmt() != null) { return toAst(stmtCtx.returnStmt()); } else if (stmtCtx.throwStmt() != null) { return toAst(stmtCtx.throwStmt()); } else if (stmtCtx.tryCatchStmt() != null) { return toAst(stmtCtx.tryCatchStmt()); } else if (stmtCtx.contextScope() != null) { return toAst(stmtCtx.contextScope()); } else { throw new UnsupportedOperationException(stmtCtx.getText()); } } private ContextScope toAst(TurinParser.ContextScopeContext ctx) { ContextScope contextScope = new ContextScope( ctx.assignments.stream().map((a)->toAst(a)).collect(Collectors.toList()), ctx.statements.stream().map((s)->toAst(s)).collect(Collectors.toList()) ); getPositionFrom(contextScope, ctx); return contextScope; } private ContextAssignment toAst(TurinParser.ContextAssignmentContext ctx) { ContextAssignment ctxAssignment = new ContextAssignment(ctx.name.getText(), toAst(ctx.expression())); getPositionFrom(ctxAssignment, ctx); return ctxAssignment; } private Expression toAst(TurinParser.AssignmentContext ctx) { AssignmentExpression node = new AssignmentExpression(toAst(ctx.target), toAst(ctx.value)); getPositionFrom(node, ctx); return node; } private TryCatchStatement toAst(TurinParser.TryCatchStmtContext ctx) { BlockStatement body = new BlockStatement(ctx.body.stream().map((s)->toAst(s)).collect(Collectors.toList())); List<CatchClause> catches = ctx.catches.stream().map((cc) -> toAst(cc)).collect(Collectors.toList()); TryCatchStatement tryCatchStatement = new TryCatchStatement(body, catches); getPositionFrom(tryCatchStatement, ctx); return tryCatchStatement; } private CatchClause toAst(TurinParser.CatchClauseContext ctx) { BlockStatement body = new BlockStatement(ctx.body.stream().map((s)->toAst(s)).collect(Collectors.toList())); TypeIdentifier type = toAst(ctx.type); CatchClause catchCause = new CatchClause(type, idText(ctx.varName), body); getPositionFrom(catchCause, ctx); return catchCause; } private ThrowStatement toAst(TurinParser.ThrowStmtContext ctx) { ThrowStatement throwStatement = new ThrowStatement(toAst(ctx.expression())); getPositionFrom(throwStatement, ctx); return throwStatement; } private Statement toAst(TurinParser.ReturnStmtContext returnStmtContext) { if (returnStmtContext.value == null) { return new ReturnStatement(); } else { return new ReturnStatement(toAst(returnStmtContext.value)); } } private Statement toAst(TurinParser.IfStmtContext ctx) { BlockStatement ifBody = new BlockStatement(ctx.ifBody.stream().map((s)->toAst(s)).collect(Collectors.toList())); List<ElifClause> elifs = ctx.elifs.stream().map((s) -> toAst(s)).collect(Collectors.toList()); if (ctx.elseBody == null) { return new IfStatement(toAst(ctx.condition), ifBody, elifs); } else { BlockStatement elseBody = new BlockStatement(ctx.elseBody.stream().map((s)->toAst(s)).collect(Collectors.toList())); return new IfStatement(toAst(ctx.condition), ifBody, elifs, elseBody); } } private ElifClause toAst(TurinParser.ElifStmtContext ctx) { BlockStatement body = new BlockStatement(ctx.body.stream().map((s)->toAst(s)).collect(Collectors.toList())); return new ElifClause(toAst(ctx.condition), body); } private VariableDeclaration toAst(TurinParser.VarDeclContext varDeclContext) { if (varDeclContext.type != null) { return new VariableDeclaration(idText(varDeclContext.name), toAst(varDeclContext.value), toAst(varDeclContext.type)); } else { return new VariableDeclaration(idText(varDeclContext.name), toAst(varDeclContext.value)); } } private Expression toAst(TurinParser.ExpressionContext exprCtx) { if (exprCtx.basicExpression() != null) { return toAst(exprCtx.basicExpression()); } else if (exprCtx.creation() != null) { return toAst(exprCtx.creation()); } else if (exprCtx.function != null) { return toAstFunctionCall(exprCtx); } else if (exprCtx.mathOperator != null) { return mathOperationToAst(exprCtx.mathOperator.getText(), exprCtx.left, exprCtx.right); } else if (exprCtx.logicOperator != null) { return logicOperationToAst(exprCtx.logicOperator.getText(), exprCtx.left, exprCtx.right); } else if (exprCtx.not != null) { return new NotOperation(toAst(exprCtx.value)); } else if (exprCtx.relOp != null) { return relationalOperationToAst(exprCtx.relOp.getText(), exprCtx.left, exprCtx.right, getPosition(exprCtx)); } else if (exprCtx.array != null) { return new ArrayAccess(toAst(exprCtx.array), toAst(exprCtx.index)); } else if (exprCtx.fieldName != null) { return toInstanceFieldAccessAst(exprCtx); } else if (exprCtx.methodName != null) { return toInstanceMethodAccessAst(exprCtx); } else if (exprCtx.isAssignment !=null) { AssignmentExpression assignmentStatement = new AssignmentExpression(toAst(exprCtx.left), toAst(exprCtx.right)); getPositionFrom(assignmentStatement, exprCtx); return assignmentStatement; } else if (exprCtx.relationSubset() != null) { return toAst(exprCtx.relationSubset()); } else { throw new UnsupportedOperationException("Enable to produce ast for " + exprCtx.getText()); } } private Expression toAst(TurinParser.RelationSubsetContext ctx) { RelationSubset relationSubset = new RelationSubset(ctx.relationName.getText(), ctx.field.getText(), ctx.actualParam().stream() .map((apCtx) -> toAst(apCtx)) .collect(Collectors.toList())); getPositionFrom(relationSubset, ctx); return relationSubset; } private InstanceMethodInvokation toInstanceMethodAccessAst(TurinParser.ExpressionContext ctx) { List<ActualParam> params = ctx.actualParam().stream().map((apCtx)->toAst(apCtx)).collect(Collectors.toList()); InstanceMethodInvokation instanceMethodInvokation = new InstanceMethodInvokation(toAst(ctx.container), idText(ctx.methodName), params); getPositionFrom(instanceMethodInvokation, ctx); return instanceMethodInvokation; } private InstanceFieldAccess toInstanceFieldAccessAst(TurinParser.ExpressionContext ctx) { InstanceFieldAccess instanceFieldAccess = new InstanceFieldAccess(toAst(ctx.container), idText(ctx.fieldName)); getPositionFrom(instanceFieldAccess, ctx); return instanceFieldAccess; } private Expression mathOperationToAst(String operatorStr, TurinParser.ExpressionContext left, TurinParser.ExpressionContext right) { Expression leftExpr = toAst(left); Expression rightExpr = toAst(right); MathOperation.Operator operator = MathOperation.Operator.fromSymbol(operatorStr); return new MathOperation(operator, leftExpr, rightExpr); } private Expression logicOperationToAst(String operatorStr, TurinParser.ExpressionContext left, TurinParser.ExpressionContext right) { Expression leftExpr = toAst(left); Expression rightExpr = toAst(right); LogicOperation.Operator operator = LogicOperation.Operator.fromSymbol(operatorStr); return new LogicOperation(operator, leftExpr, rightExpr); } private Expression relationalOperationToAst(String operatorStr, TurinParser.ExpressionContext left, TurinParser.ExpressionContext right, Position position) { Expression leftExpr = toAst(left); Expression rightExpr = toAst(right); RelationalOperation.Operator operator = RelationalOperation.Operator.fromSymbol(operatorStr); RelationalOperation relationalOperation = new RelationalOperation(operator, leftExpr, rightExpr); relationalOperation.setPosition(position); return relationalOperation; } private Expression toAst(TurinParser.BasicExpressionContext exprCtx) { if (exprCtx.valueReference() != null) { return toAst(exprCtx.valueReference()); } else if (exprCtx.interpolatedStringLiteral() != null) { return toAst(exprCtx.interpolatedStringLiteral()); } else if (exprCtx.byteLiteral() != null) { return toAst(exprCtx.byteLiteral()); } else if (exprCtx.shortLiteral() != null) { return toAst(exprCtx.shortLiteral()); } else if (exprCtx.intLiteral() != null) { return toAst(exprCtx.intLiteral()); } else if (exprCtx.longLiteral() != null) { return toAst(exprCtx.longLiteral()); } else if (exprCtx.floatLiteral() != null) { return toAst(exprCtx.floatLiteral()); } else if (exprCtx.doubleLiteral() != null) { return toAst(exprCtx.doubleLiteral()); } else if (exprCtx.parenExpression() != null) { return toAst(exprCtx.parenExpression().internal); } else if (exprCtx.stringLiteral() != null) { return toAst(exprCtx.stringLiteral()); } else if (exprCtx.booleanLiteral() != null) { return new BooleanLiteral(exprCtx.booleanLiteral().positive != null); } else if (exprCtx.staticFieldReference() != null) { return toAst(exprCtx.staticFieldReference()); } else if (exprCtx.placeholderUsage() != null) { return toAst(exprCtx.placeholderUsage()); } else if (exprCtx.placeholderNameUsage() != null) { return toAst(exprCtx.placeholderNameUsage()); } else if (exprCtx.thisReference() != null) { ThisExpression thisExpression = new ThisExpression(); getPositionFrom(thisExpression, exprCtx.thisReference()); return thisExpression; } else if (exprCtx.contextAccess() != null) { return toAst(exprCtx.contextAccess()); } else { throw new UnsupportedOperationException(exprCtx.getText()); } } private ContextAccess toAst(TurinParser.ContextAccessContext ctx) { ContextAccess contextAccess = new ContextAccess(ctx.field.getText()); getPositionFrom(contextAccess, ctx); return contextAccess; } private Expression toAst(TurinParser.PlaceholderUsageContext ctx) { ParserRuleContext parent = ctx.getParent(); String fieldName = null; while (parent != null && fieldName == null) { if (parent instanceof TurinParser.InTypePropertyDeclarationContext) { fieldName = idText(((TurinParser.InTypePropertyDeclarationContext)parent).name); } else { parent = parent.getParent(); } } if (fieldName == null) { return new SemanticError("A placeholder should be used only inside in-type property declarations", getPosition(ctx)); } else { Placeholder placeholder = new Placeholder(); getPositionFrom(placeholder, ctx); return placeholder; } } private Expression toAst(TurinParser.PlaceholderNameUsageContext ctx) { ParserRuleContext parent = ctx.getParent(); String fieldName = null; while (parent != null && fieldName == null) { if (parent instanceof TurinParser.InTypePropertyDeclarationContext) { fieldName = idText(((TurinParser.InTypePropertyDeclarationContext)parent).name); } else { parent = parent.getParent(); } } if (fieldName == null) { return new SemanticError("A placeholder should be used only inside in-type property declarations", getPosition(ctx)); } else { StringLiteral stringLiteral = new StringLiteral(fieldName); getPositionFrom(stringLiteral, ctx); return stringLiteral; } } private Expression toAst(TurinParser.StaticFieldReferenceContext ctx) { StaticFieldAccess staticFieldAccess = new StaticFieldAccess(toAst(ctx.typeReference()), idText(ctx.name)); getPositionFrom(staticFieldAccess, ctx); return staticFieldAccess; } private TypeIdentifier toAst(TurinParser.TypeReferenceContext ctx) { if (ctx.packag != null) { return new TypeIdentifier(toAst(ctx.packag), idText(ctx.name)); } else { return new TypeIdentifier(idText(ctx.name)); } } private String idText(Token token) { if (token.getText().startsWith("v#") || token.getText().startsWith("T#")) { return token.getText().substring(2); } else { return token.getText(); } } private ValueReference toAst(TurinParser.ValueReferenceContext valueReferenceContext) { ValueReference expression = new ValueReference(idText(valueReferenceContext.name)); getPositionFrom(expression, valueReferenceContext); return expression; } private String unescape(String s) { switch (s) { case "\\r": return "\r"; case "\\n": return "\n"; case "\\b": return "\b"; case "\\f": return "\f"; case "\\t": return "\t"; case "\\\\": return "\\"; case "\\\"": return "\""; default: throw new UnsupportedOperationException(s); } } private Expression toAst(TurinParser.InterpolatedStringLiteralContext interpolatedStringLiteralContext) { StringInterpolation stringInterpolation = new StringInterpolation(); for (TurinParser.StringElementContext element :interpolatedStringLiteralContext.elements){ if (element.stringInterpolationElement() != null) { stringInterpolation.add(toAst(element.stringInterpolationElement())); } else if (element.STRING_CONTENT() != null) { stringInterpolation.add(new StringLiteral(element.STRING_CONTENT().getText())); } else if (element.ESCAPE_SEQUENCE() != null) { stringInterpolation.add(new StringLiteral(unescape(element.ESCAPE_SEQUENCE().getText()))); } else { throw new UnsupportedOperationException(); } } getPositionFrom(stringInterpolation, interpolatedStringLiteralContext); return stringInterpolation; } private Expression toAst(TurinParser.StringInterpolationElementContext stringInterpolationElementContext) { return toAst(stringInterpolationElementContext.expression()); } private Creation toAst(TurinParser.CreationContext ctx) { Creation creation = new Creation(toAst(ctx.ref), ctx.actualParam().stream().map((apCtx)->toAst(apCtx)).collect(Collectors.toList())); getPositionFrom(creation, ctx); return creation; } private ActualParam toAst(TurinParser.ActualParamContext apCtx) { ActualParam actualParam; if (apCtx.name != null) { actualParam = new ActualParam(idText(apCtx.name), toAst(apCtx.expression())); } else { actualParam = new ActualParam(toAst(apCtx.expression()), apCtx.asterisk != null); } getPositionFrom(actualParam, apCtx); return actualParam; } private FunctionCall toAstFunctionCall(TurinParser.ExpressionContext functionCallContext) { Expression function = toAst(functionCallContext.function); return new FunctionCall(function, functionCallContext.actualParam().stream().map((apCtx)->toAst(apCtx)).collect(Collectors.toList())); } private Expression toAst(TurinParser.ByteLiteralContext ctx) { try { // ignore last character String text = ctx.getText().substring(0, ctx.getText().length() - 1); BigInteger bigInteger = new BigInteger(text); if (bigInteger.compareTo(new BigInteger(Byte.toString(Byte.MAX_VALUE))) == 1 || bigInteger.compareTo(new BigInteger(Byte.toString(Byte.MIN_VALUE))) == -1) { return new SemanticError("Value cannot be contained in the given type", getPosition(ctx)); } ByteLiteral literal = new ByteLiteral(Byte.parseByte(text)); getPositionFrom(literal, ctx); return literal; } catch (NumberFormatException e){ return new SemanticError("Invalid number literal", getPosition(ctx)); } } private Expression toAst(TurinParser.ShortLiteralContext ctx) { try { // ignore last character String text = ctx.getText().substring(0, ctx.getText().length() - 1); BigInteger bigInteger = new BigInteger(text); if (bigInteger.compareTo(new BigInteger(Short.toString(Short.MAX_VALUE))) == 1 || bigInteger.compareTo(new BigInteger(Short.toString(Short.MIN_VALUE))) == -1) { return new SemanticError("Value cannot be contained in the given type", getPosition(ctx)); } ShortLiteral literal = new ShortLiteral(Short.parseShort(text)); getPositionFrom(literal, ctx); return literal; } catch (NumberFormatException e){ return new SemanticError("Invalid number literal", getPosition(ctx)); } } private Expression toAst(TurinParser.IntLiteralContext ctx) { try { BigInteger bigInteger = new BigInteger(ctx.getText()); if (bigInteger.compareTo(new BigInteger(Integer.toString(Integer.MAX_VALUE))) == 1 || bigInteger.compareTo(new BigInteger(Integer.toString(Integer.MIN_VALUE))) == -1) { return new SemanticError("Value cannot be contained in the given type", getPosition(ctx)); } IntLiteral intLiteral = new IntLiteral(Integer.parseInt(ctx.getText())); getPositionFrom(intLiteral, ctx); return intLiteral; } catch (NumberFormatException e){ return new SemanticError("Invalid number literal", getPosition(ctx)); } } private Expression toAst(TurinParser.LongLiteralContext ctx) { try { // ignore last character String text = ctx.getText().substring(0, ctx.getText().length() - 1); BigInteger bigInteger = new BigInteger(text); if (bigInteger.compareTo(new BigInteger(Long.toString(Long.MAX_VALUE))) == 1 || bigInteger.compareTo(new BigInteger(Long.toString(Long.MIN_VALUE))) == -1) { return new SemanticError("Value cannot be contained in the given type", getPosition(ctx)); } LongLiteral literal = new LongLiteral(Long.parseLong(text)); getPositionFrom(literal, ctx); return literal; } catch (NumberFormatException e){ return new SemanticError("Invalid number literal", getPosition(ctx)); } } private Expression toAst(TurinParser.FloatLiteralContext ctx) { try { // ignore last character String text = ctx.getText().substring(0, ctx.getText().length() - 1); FloatLiteral literal = new FloatLiteral(Float.parseFloat(text)); getPositionFrom(literal, ctx); return literal; } catch (NumberFormatException e){ return new SemanticError("Invalid number literal", getPosition(ctx)); } } private Expression toAst(TurinParser.DoubleLiteralContext ctx) { try { DoubleLiteral literal = new DoubleLiteral(Double.parseDouble(ctx.getText())); getPositionFrom(literal, ctx); return literal; } catch (NumberFormatException e){ return new SemanticError("Invalid number literal", getPosition(ctx)); } } private StringLiteral toAst(TurinParser.StringLiteralContext stringLiteralContext) { String content = stringLiteralContext.getText().substring(1, stringLiteralContext.getText().length() - 1); StringLiteral stringLiteral = new StringLiteral(content); getPositionFrom(stringLiteral, stringLiteralContext); return stringLiteral; } private ExpressionStatement toAst(TurinParser.ExpressionStmtContext expressionStmtContext) { return new ExpressionStatement(toAst(expressionStmtContext.expression())); } private NamespaceDefinition toAst(TurinParser.NamespaceDeclContext namespaceContext) { // in this way we take care of the escaped IDs return new NamespaceDefinition(toAst(namespaceContext.name).qualifiedName()); } }